package com.ibm.mongo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ibm.interfaces.INoSqlDB;
import com.ibm.interfaces.IResultCursor;
import com.ibm.util.ErrorCode;
import com.ibm.util.JSONUtility;
import com.ibm.util.exception.CPSException;

public class CollectionAccess {
	private static final String ID = "id";
	final private INoSqlDB db;

	public CollectionAccess(INoSqlDB db) {
		this.db = db;
	}

	public void put(int collectionId, ObjectNode document, String keyFieldName)
			throws CPSException {
		HashSet<String> fields = new HashSet<String>();
		setObjectId(document, keyFieldName);
		Iterator<String> names = document.fieldNames();
		while (names.hasNext()) {
			fields.add(names.next());
		}
		db.upsert(collectionId, document, ID, fields);
	}
	
	public void post(int collectionId, ObjectNode document, String keyFieldName)
			throws CPSException {
		HashSet<String> fields = new HashSet<String>();
		setObjectId(document, keyFieldName);
		Iterator<String> names = document.fieldNames();
		while (names.hasNext()) {
			fields.add(names.next());
		}
		db.insert(collectionId, document, ID, fields);
	}

	public Collection<String> get(int collectionId, ObjectNode filterCondition,
			String keyFieldName) throws CPSException {
		if (filterCondition.has(keyFieldName)) {
			setObjectId(filterCondition, keyFieldName);
		}
		IResultCursor<ObjectNode> cursor = db.find(collectionId,
				filterCondition, false, ID);
		Collection<String> result = new ArrayList<String>();
		while (cursor != null && cursor.hasNext()) {
			ObjectNode element = cursor.next();
			resetObjectId(element, keyFieldName);
			result.add(element.toString());
		}
		return result;
	}

	public Collection<String> delete(int collectionId,
			ObjectNode filterCondition, String keyFieldName)
			throws CPSException {
		Collection<String> result = get(collectionId, filterCondition,
				keyFieldName);
		for (String element : result) {
			ObjectNode doc = JSONUtility.fromObjectString(element);
			db.delete(collectionId, doc.get(keyFieldName).asText());
		}
		return result;
	}

	private void resetObjectId(ObjectNode document, String keyFieldName)
			throws CPSException {
		if (document.get(ID) == null) {
			throw new CPSException(ErrorCode.INPUT_ERROR,
					"There should contain field id in document " + document);
		}
		String keyValue = document.get(ID).asText();
		document.put(keyFieldName, keyValue);
		document.remove(ID);
	}

	private void setObjectId(ObjectNode document, String keyFieldName)
			throws CPSException {

		if (document.get(keyFieldName) == null) {
			throw new CPSException(ErrorCode.INVALID_INPUT_ERROR,
					"The value of key " + keyFieldName
							+ " should not be null in " + document.toString());
		}
		String keyValue = document.get(keyFieldName).asText();
		document.put(ID, keyValue);
		document.remove(keyFieldName);
	}

}
